package com.gulimall.authserver.controller;

import com.alibaba.csp.sentinel.util.StringUtil;
import com.gulimall.authserver.config.MyEmailConfigProperties;
import com.gulimall.authserver.constant.AutoServerConstant;
import com.gulimall.authserver.feign.MemberFeignService;
import com.gulimall.authserver.vo.UserLoginVo;
import com.gulimall.authserver.vo.UserRegisterVo;
import com.gulimall.common.constant.AuthServerConstant;
import com.gulimall.common.exception.BizCodeEnum;
import com.gulimall.common.utils.R;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.HtmlEmail;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Controller
public class LoginController {

    @Autowired
    private MyEmailConfigProperties properties;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private MemberFeignService memberFeignService;

    @GetMapping("/sendEmail")
    @ResponseBody
    public R sendCode(@RequestParam("email") String email) throws EmailException {
        String key = AutoServerConstant.SMS_CODE_CACHE_PREFIX + email;
        String redisCode = redisTemplate.opsForValue().get(key);
        if (!StringUtil.isBlank(redisCode)) {
            long expireTime = Long.parseLong(redisCode.split("_")[1]);
            if (System.currentTimeMillis() - expireTime < 60000) {
                return R.error(BizCodeEnum.SMS_CODE_EXCEPTION.getCode(), BizCodeEnum.SMS_CODE_EXCEPTION.getMessage());
            }
        }

        StringBuilder code = sendEmail(email);
        code.append("_").append(System.currentTimeMillis());
        redisTemplate.opsForValue().set(key, code.toString(), 10, TimeUnit.MINUTES);
        return R.ok().put("code", code.toString());
    }

    private StringBuilder sendEmail(String num) throws EmailException {
        HtmlEmail email = new HtmlEmail();
        //邮箱的SMTP服务器，一般123邮箱的是smtp.123.com,qq邮箱为smtp.qq.com
        email.setHostName(properties.getHost());
        //设置发送的字符类型
        email.setCharset(properties.getCharset());
        //设置发送人到邮箱和授权码(授权码是自己设置的)
        email.setAuthentication(properties.getUsername(), properties.getPassword());
        email.setFrom("3299686223@qq.com", "10000");
        //设置收件人
        email.addTo(num);
        //设置发送主题
        email.setSubject(AutoServerConstant.SUBJECT);
        StringBuilder code = new StringBuilder();
        Random random = new Random();
        //随机数
        for (int i = 0; i < 4; i++) {
            code.append(random.nextInt(10));
        }
        //设置发送内容
        email.setMsg(AutoServerConstant.MSG + code);

        //进行发送
        email.send();
        return code;
    }

    @PostMapping("/register")
    public String region(@Valid UserRegisterVo registerVo, BindingResult result, RedirectAttributes redirectAttributes) {
        //校验出错转发
        Map<String, String> errors = new HashMap<>();
        if (result.hasErrors()) {
            errors = result.getFieldErrors().stream().collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage));
            redirectAttributes.addFlashAttribute("errors", errors);
            return "redirect:http://auth.gulimall.com/reg.html";
        }
        String redisKey = AutoServerConstant.SMS_CODE_CACHE_PREFIX + registerVo.getPhone();
        String code = registerVo.getCode();
        String redisCode = redisTemplate.opsForValue().get(redisKey);
        if (!StringUtils.isEmpty(redisCode) && redisCode.split("_")[0].equals(code)) {
            redisTemplate.delete(redisKey);
            R res = memberFeignService.register(registerVo);
            if (res.getCode() != 0) {
                errors.put("msg", res.getMsg());
                redirectAttributes.addFlashAttribute("errors", errors);
                return "redirect:http://auth.gulimall.com/reg.html";
            }
        } else {
            errors.put("code", "验证码出错");
            redirectAttributes.addFlashAttribute("errors", errors);
            return "redirect:http://auth.gulimall.com/reg.html";
        }
        return "redirect:http://auth.gulimall.com/login.html";
    }

    @PostMapping("/login")
    public String login(UserLoginVo vo, RedirectAttributes redirectAttributes, HttpSession session) {
        R login = memberFeignService.login(vo);
        if (login.getCode() != 0) {
            Map<String, String> errors = new HashMap<>();
            errors.put("msg", login.getMsg());
            redirectAttributes.addFlashAttribute("errors", errors);
            return "redirect:http://auth.gulimall.com/login.html";
        }
        //登录成功放人session中
        Object data = login.getData("data");
        session.setAttribute(AuthServerConstant.LOGIN_USER, data);
        return "redirect:http://gulimall.com/index.html";
    }

    @GetMapping("/login.html")
    public String loginPage(HttpSession session) {
        Object attribute = session.getAttribute(AuthServerConstant.LOGIN_USER);
        return Objects.isNull(attribute) ? "/login" : "redirect:http://gulimall.com/index.html";
    }

    @GetMapping("/logout")
    public String logout(HttpSession session) {
        session.removeAttribute(AuthServerConstant.LOGIN_USER);
        return "redirect:http://gulimall.com/index.html";
    }
}
